home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / datetostr.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  5KB  |  217 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: datetostr.c,v 1.3 1996/08/13 13:52:53 digulla Exp $
  4.     $Log: datetostr.c,v $
  5.     Revision 1.3  1996/08/13 13:52:53  digulla
  6.     Replaced <dos/dosextens.h> by "dos_intern.h" or added "dos_intern.h"
  7.     Replaced __AROS_LA by __AROS_LHA
  8.  
  9.     Revision 1.2  1996/08/01 17:40:48  digulla
  10.     Added standard header for all files
  11.  
  12.     Desc:
  13.     Lang: english
  14. */
  15. #include <dos/datetime.h>
  16. #include "dos_intern.h"
  17.  
  18. /*****************************************************************************
  19.  
  20.     NAME */
  21.     #include <clib/dos_protos.h>
  22.  
  23.     __AROS_LH1(BOOL, DateToStr,
  24.  
  25. /*  SYNOPSIS */
  26.     __AROS_LHA(struct DateTime *, datetime, D1),
  27.  
  28. /*  LOCATION */
  29.     struct DosLibrary *, DOSBase, 124, Dos)
  30.  
  31. /*  FUNCTION
  32.  
  33.     INPUTS
  34.  
  35.     RESULT
  36.  
  37.     NOTES
  38.  
  39.     EXAMPLE
  40.  
  41.     BUGS
  42.  
  43.     SEE ALSO
  44.  
  45.     INTERNALS
  46.  
  47.     HISTORY
  48.     29-10-95    digulla automatically created from
  49.                 dos_lib.fd and clib/dos_protos.h
  50.  
  51. *****************************************************************************/
  52. {
  53.     __AROS_FUNC_INIT
  54.     __AROS_BASE_EXT_DECL(struct DosLibrary *,DOSBase)
  55.  
  56.     /* Starting days of the months in a leap year. */
  57.     const ULONG daytabl[]=
  58.     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
  59.  
  60.     char *const monthtable[]=
  61.     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  62.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  63.  
  64.     char *const weektable[]=
  65.     { "Sunday", "Monday", "Tuesday", "Wednesday",
  66.       "Thursday", "Friday", "Saturday" };
  67.  
  68.     STRPTR buf, name, fstring;
  69.  
  70.     LONG year, month, days, mins, tick, leap=1;
  71.  
  72.     /* Read time. */
  73.     days=datetime->dat_Stamp.ds_Days;
  74.     mins=datetime->dat_Stamp.ds_Minute;
  75.     tick=datetime->dat_Stamp.ds_Tick;
  76.  
  77.     /*
  78.     Check if timestamp is correct. Correct timestamps lie
  79.     between the 1.1.1978 0:00:00 and the 11.7.5881588 23:59:59.
  80.     */
  81.     if(days<0||(ULONG)mins>=24*60||(ULONG)tick>=TICKS_PER_SECOND*60)
  82.     return 0;
  83.  
  84.     if(datetime->dat_StrDay!=NULL)
  85.     {
  86.     /* Get weekday name. The 1.1.1978 was a sunday. */
  87.     buf=datetime->dat_StrDay;
  88.     name=weektable[days%7];
  89.     while((*buf++=*name++)!=0)
  90.         ;
  91.     }
  92.  
  93.     if(datetime->dat_StrDate!=NULL)
  94.     {
  95.     /*
  96.         Calculate year and the days in the year. Use a short method
  97.         if the date is between the 1.1.1978 and the 1.1.2100:
  98.         Every year even divisible by 4 in this time span is a leap year.
  99.         There are 92 normal and 30 leap years there.
  100.     */
  101.     if(days<92*365+30*365)
  102.     {
  103.         /*
  104.         1976 was a leap year so use it as a base to divide the days
  105.         into 4-year blocks (each beginning with a leap year).
  106.         */
  107.         days+=366+365;
  108.         year=4*(days/(366+3*365))+1976;
  109.         days%=(366+3*365);
  110.         /* Now divide the 4-year blocks into single years. */
  111.         if(days>=366)
  112.         {
  113.         leap=0;
  114.         days--;
  115.         year+=days/365;
  116.         days%=365;
  117.         }
  118.     }else
  119.     {
  120.         /*
  121.         The rule for calendar calculations are:
  122.         1. Every year even divisible by 4 is a leap year.
  123.         2. As an exception from rule 1 every year even divisible by
  124.            100 is not.
  125.         3. Every year even divisible by 400 is a leap year as an
  126.            exception from rule 2.
  127.         So 1996, 2000 and 2004 are leap years - 1900 and 1999 are not.
  128.  
  129.         Use 2000 as a base to devide the days into 400 year blocks,
  130.         those into 100 year blocks and so on...
  131.         */
  132.         days-=17*365+5*366;
  133.         year=400*(days/(97*366+303*365))+2000;
  134.         days%=(97*366+303*365);
  135.         if(days>=366)
  136.         {
  137.         leap=0;
  138.         days--;
  139.         year+=100*(days/(24*366+76*365));
  140.         days%=(24*366+76*365);
  141.         if(days>=365)
  142.         {
  143.             leap=1;
  144.             days++;
  145.             year+=4*(days/(366+3*365));
  146.             days%=(366+3*365);
  147.             if(days>=366)
  148.             {
  149.             leap=0;
  150.             days--;
  151.             year+=days/365;
  152.             days%=365;
  153.             }
  154.         }
  155.         }
  156.     }
  157.     /*
  158.          The starting-day table assumes a leap year - so add one day if
  159.          the date is after february 28th and the year is no leap year.
  160.     */
  161.     if(!leap&&days>=31+28)
  162.         days++;
  163.     for(month=11;;month--)
  164.         if(days>=daytabl[month])
  165.         {
  166.         days-=daytabl[month];
  167.         break;
  168.         }
  169.     /* Remember that 0 means 1.1.1978. */
  170.     days++;
  171.  
  172.     /* Build date string */
  173.     buf=datetime->dat_StrDate;
  174.     fstring="d-m-y";
  175.     do
  176.         switch(*fstring)
  177.         {
  178.         case 'y':
  179.             *buf++=year/10%10+'0';
  180.             *buf++=year%10+'0';
  181.             break;
  182.         case 'm':
  183.             name=monthtable[month];
  184.             while(*name)
  185.             *buf++=*name++;
  186.             break;
  187.         case 'd':
  188.             *buf++=days/10+'0';
  189.             *buf++=days%10+'0';
  190.             break;
  191.         default:
  192.             *buf++=*fstring;
  193.             break;
  194.         }
  195.     while(*fstring++);
  196.     }
  197.  
  198.     if(datetime->dat_StrTime!=NULL)
  199.     {
  200.     /* Build time string */
  201.     datetime->dat_StrTime[0]=mins/(10*60)+'0';
  202.     datetime->dat_StrTime[1]=mins/60%10+'0';
  203.     datetime->dat_StrTime[2]=':';
  204.     datetime->dat_StrTime[3]=mins/10%6+'0';
  205.     datetime->dat_StrTime[4]=mins%10+'0';
  206.     datetime->dat_StrTime[5]=':';
  207.     datetime->dat_StrTime[6]=tick/(10*TICKS_PER_SECOND)+'0';
  208.     datetime->dat_StrTime[7]=tick/TICKS_PER_SECOND%10+'0';
  209.     datetime->dat_StrTime[8]=0;
  210.     }
  211.  
  212.     /* All done. Return OK. */
  213.     return 1;
  214.  
  215.     __AROS_FUNC_EXIT
  216. } /* DateToStr */
  217.